﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Bystd.Geo.Geometries
{ 
    /// <summary>
    /// 读法经纬度/xy
    /// </summary>
    public class Coordinate
    {  
        /// <summary>
        /// 经度
        /// </summary>
        public double X { get; set; }
        /// <summary>
        /// 纬度
        /// </summary>
        public double Y { get; set; }

        public double Z { get; set; }

        public Coordinate()
        { }

        public Coordinate(double X,double Y)
        {
            this.X = X;
            this.Y = Y;
        }

        public Coordinate(double X,double Y,double Z)
        {
            this.X = X;
            this.Y = Y;
            this.Z = Z;
        }

        public bool Equals(Coordinate coord,double tolerance=0)
        {
            bool isEqual = Math.Abs(coord.X - X)<=tolerance;
            if (isEqual == false) return false;

            isEqual = Math.Abs(coord.Y - Y) <= tolerance;
            if (isEqual == false) return false;

            isEqual = Math.Abs(coord.Z - Z) <= tolerance;
            return isEqual;
        }

        public bool Equals2D(Coordinate coord, double tolerance = 0)
        {
            bool isEqual = Math.Abs(coord.X - X) <= tolerance;
            if (isEqual == false) return false;

            isEqual = Math.Abs(coord.Y - Y) <= tolerance;
            if (isEqual == false) return false;

            return isEqual;
        }

        public static bool operator >(Coordinate s, Coordinate d)
        {
            bool greater = (d.X > d.X && s.Y > d.Y);
            if (s.Z == d.Z) return greater;
            return greater & (s.Z > d.Z);
        }

        public static bool operator <(Coordinate s, Coordinate d)
        {
            bool greater = (d.X < d.X && s.Y < d.Y);
            if (s.Z == d.Z) return greater;
            return greater & (s.Z < d.Z);
        }

        public static bool operator <=(Coordinate s, Coordinate d)
        {
            if (d.X <= d.X && s.Y <= d.Y && s.Z <= d.Z) return true;
            return false;
        }

        public static bool operator >=(Coordinate s, Coordinate d)
        {
            if (d.X >= d.X && s.Y >= d.Y && s.Z >= d.Z) return true;
            return false;
        }

        public Coordinate Min(Coordinate point, bool hasZ = false)
        {
            double minX = this.X < point.X ? this.X : point.X;
            double minY = this.Y < point.Y ? this.Y : point.Y;
            double minZ = 0;
            if (hasZ)
                minZ = this.Z < point.Z ? this.Z : point.Z;

            return new Coordinate(minX, minY, minZ);
        }

        public Coordinate Copy()
        {
            return new Coordinate(this.X, this.Y, this.Z);
        }

        public double MinX(Coordinate point)
        {
            return this.X > point.X ? point.X : this.X;
        }

        public double MinY(Coordinate point)
        {
            return this.Y > point.Y ? point.Y : this.Y;
        }

        public double MaxX(Coordinate point)
        {
            return this.X > point.X ? this.X : point.X;
        }

        public double MaxY(Coordinate point)
        {
            return this.Y > point.Y ? this.Y : point.Y;
        }

        public Coordinate Max(Coordinate point, bool hasZ = false)
        {
            double maxX = this.X > point.X ? this.X : point.X;
            double maxY = this.Y > point.Y ? this.Y : point.Y;
            double maxZ = 0;
            if (hasZ)
                maxZ = this.Z > point.Z ? this.Z : point.Z;

            return new Coordinate(maxX, maxY, maxZ);
        }

        public double Distance(Coordinate end)
        {
            return Math.Sqrt(Math.Pow(end.X - X, 2) + Math.Pow(end.Y - Y, 2));
        }

        public double DistanceSquard(Coordinate end)
        {
            return Math.Pow(end.X - X, 2) + Math.Pow(end.Y - Y, 2);
        }

        public string To2DString(string split)
        {
            return string.Format("{0}{1}{2}", X, split, Y);
        }

        public override string ToString()
        {
            return string.Format("{0},{1},{2}", X, Y, Z);
        }
    }

    public class CoordinateRange
    {
        public double Min { get; set; }

        public double Max { get; set; }

        public CoordinateRange() { }

        public CoordinateRange(double Min, double Max)
        {
            this.Max = Max;
            this.Min = Min;
        }

    }
}
